﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;
using Ue.Core.DynamicReflection;

namespace Ue.Extensions
{
    public static class ControlValueExtensions
    {
        static class ControlValueMappingCachesHolder
        {
            public static ConcurrentDictionary<Type, PropertyInfo> controlValueMappingCaches = new ConcurrentDictionary<Type, PropertyInfo>();
        }

        private static IDictionary<Type, PropertyInfo> ControlValueMappingCaches
        {
            get { return ControlValueMappingCachesHolder.controlValueMappingCaches; }
        }

        /// <summary>
        /// 取得控件设置值的属性
        /// 如：TextBox控件的Text
        ///     DropDownList控件的SelectedValue
        ///     CheckBox控件的Checked
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public static PropertyInfo GetControlValueProperty(this Control control)
        {
            if (null == control)
            {
                return null;
            }

            Type entityType = control.GetType();

            if (!ControlValueExtensions.ControlValueMappingCaches.ContainsKey(entityType))
            {
                //有一些控件是获取不到ControlValuePropertyAttribute的，例如：Literal

                var valuePropertyName = string.Empty;
                var controlValuePropertyAttribute = entityType.GetCustomAttributes(typeof(ControlValuePropertyAttribute), true);

                if (controlValuePropertyAttribute.Length > 0)
                {
                    valuePropertyName = ((ControlValuePropertyAttribute)controlValuePropertyAttribute[0]).Name;
                }

                if (string.IsNullOrEmpty(valuePropertyName) && control is ITextControl)
                {
                    valuePropertyName = "Text";
                }

                if (string.IsNullOrEmpty(valuePropertyName))
                {
                    throw new ArgumentOutOfRangeException(string.Format("控件{0}没有ControlValuePropertyAttribute标签。Control.Type：{1}", control.ID, control.GetType()));
                }

                ControlValueExtensions.ControlValueMappingCaches[entityType] = entityType.GetProperty(valuePropertyName);
            }

            return ControlValueExtensions.ControlValueMappingCaches[entityType];
        }

        /// <summary>
        /// 设置控件值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <param name="value"></param>
        public static void SetValue<T>(this Control control,T value)
        {
            PropertyInfo property= control.GetControlValueProperty();
            if (property != null && property.CanWrite)
            {
                property.DynamicPropertySetValue(control, value);
            }
        }

        public static object GetValue(this Control control)
        {
            PropertyInfo property = control.GetControlValueProperty();
            if (property != null && property.CanRead)
            {
                return property.DynamicPropertyGetValue(control);
            }

            return null;
        }
        /// <summary>
        /// 获取控件值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="control"></param>
        /// <returns></returns>
        public static T GetValue<T>(this Control control, T defaultValue)
        {
            var value = control.GetValue();

            return value == null

                ? defaultValue
            : value.As<T>(defaultValue);
        }
        public static T GetValue<T>(this Control control)
        {
            return control.GetValue<T>(default(T));
        }


        public static T FindControl<T>(this Control col, string id)
            where T : Control
        {
            return (T)col.FindControl(id);
        }
    }
}
